namespace Pdf
{
    inline Parser::Parser(std::istream *stream) : streambuf( stream->rdbuf() )
    {    }

    inline Parser::~Parser()
    {    
		while ( !factories.empty() )
		{
			delete factories.back();
			factories.pop_back();
		}
	}

    inline Object::Ptr Parser::read()
    {
        std::streambuf::int_type c = streambuf->sgetc();

        while ( c != std::streambuf::traits_type::eof() && object == 0 )
            c = scanNext( c, streambuf );

        Object::Ptr obj;
        obj.swap( object );
        return obj;
    }

    inline void Parser::skipEOL()
    {    scanEOL( streambuf->sgetc(), streambuf );    }

    template <typename TargetType>
    typename TargetType::Ptr Parser::read()
    {
        Object::Ptr obj = read();
        return TargetType::Ptr( obj ? cast<TargetType*>( obj ) : 0 );
    }

    inline void Parser::push(ObjectFactory* factory)
    {    factories.push_back(factory);    }

    inline void Parser::pop()
    {
        assert( !factories.empty() );

        Object::Ptr obj = factories.back()->create();

		delete factories.back();
        factories.pop_back();

        if ( factories.empty() )
            object = obj;
        else
            factories.back()->append( obj );
    }

    inline void Parser::onCharacter(char c)
    {
        if ( !factories.empty() )
            factories.back()->append( c );
    }

    inline void Parser::onEnterWhiteSpace()
    {    }

    inline void Parser::onLeaveWhiteSpace()
    {    }

    inline void Parser::onEnterEOL()
    {    }

    inline void Parser::onLeaveEOL()
    {    }

    inline void Parser::onEnterComment()
    {    }

    inline void Parser::onLeaveComment()
    {    }

    inline void Parser::onEnterString()
    {   push( new StringFactory() );    }

    inline void Parser::onLeaveString()
    {   pop();    }

    inline void Parser::onEnterDictionary()
    {   push( new DictionaryFactory() );    }

    inline void Parser::onLeaveDictionary()
    {   pop();    }

    inline void Parser::onEnterName()
    {   push( new NameFactory() );    }

    inline void Parser::onLeaveName()
    {   pop();    }

    inline void Parser::onEnterArray()
    {   push( new ArrayFactory() );    }

    inline void Parser::onLeaveArray()
    {   pop();    }

    inline void Parser::onEnterNames()
    {   push( new NamesFactory() );    }

    inline void Parser::onLeaveNames()
    {   pop();    }

    inline void Parser::onEnterToken()
    {   push( new TokenFactory() );    }

    inline void Parser::onLeaveToken()
    {   pop();    }
}